package admin;

import auth.Registration;
import content.GroupContent;
import entity.AddressLocal;
import entity.AddressLocalHome;
import entity.GroupsLocal;
import entity.GroupsLocalHome;
import entity.UsersLocal;
import entity.UsersLocalHome;
import helper.SimpleJSONObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import transfer.Address;
import transfer.Group;
import transfer.User;
import transfer.UserRole;

/**
 *
 * @author rebelizant
 */
public class UserOperation extends HttpServlet {
    
    public static final String action = "action";
    public static final String createAction = "create";
    public static final String editAction = "edit";
    
    public static final String roles = "roles";
    public static final String groups = "groups";
    public static final String splitter = ";";
    public static final String userIdParameter = "userId";

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String act = request.getParameter(action);
        if (createAction.equals(act)) {
            createUser(request, response);
        }
        if (editAction.equals(act)) {
            editUser(request, response);
        }
    }
    
    private void createUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/Registration").forward(request, response);
        String rolesString = request.getParameter(roles);
        String[] rls = rolesString.split(splitter);
        Integer[] rolesNumber = new Integer[rls.length];
        for (int i = 0; i < rls.length; i++) {
            rolesNumber[i] = new Integer(rls[i]);
        }
        String groupsString = request.getParameter(groups);
        String[] grps = groupsString.split(splitter);
        Integer[] groupsNumber = new Integer[grps.length];
        for (int i = 0; i < grps.length; i++) {
            if (!grps[i].equals("")) {
                groupsNumber[i] = new Integer(grps[i]);
            }
        }
        try {
            InitialContext context = new InitialContext();
            UsersLocalHome homeUser = (UsersLocalHome) context.lookup("java:comp/env/Users");
            UsersLocal local = homeUser.findByLog(request.getParameter(Registration.loginParameter));
            User user = local.getUser();
            ArrayList userRoles = new ArrayList(user.getRoles());
            for (int i = 0; i < rolesNumber.length; i++) {
                UserRole ur = UserRole.instance(rolesNumber[i]);
                if (!userRoles.contains(ur)) {
                    userRoles.add(ur);
                }
            }
            user.setRoles(userRoles);
            local.setUser(user);
            GroupsLocalHome homeGroup = (GroupsLocalHome) context.lookup("java:comp/env/Groups");
            for (int i = 0; i < groupsNumber.length; i++) {
                GroupsLocal groupsLocal = homeGroup.findByPrimaryKey(groupsNumber[i]);
                Group group = groupsLocal.getGroup();
                ArrayList users = new ArrayList(group.getUsers());
                if (!users.contains(user)) {
                    users.add(user);
                }
                group.setUsers(users);
                groupsLocal.setGroup(group);
            }
        } catch (NamingException ex) {
            ex.printStackTrace();
        } catch (FinderException ex) {
            ex.printStackTrace();
        }
    }
    
    private void editUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String rolesString = request.getParameter(roles);
        String[] rls = rolesString.split(splitter);
        Integer[] rolesNumber = new Integer[rls.length];
        for (int i = 0; i < rls.length; i++) {
            rolesNumber[i] = new Integer(rls[i]);
        }
        String groupsString = request.getParameter(groups);
        String[] grps = groupsString.split(splitter);        
        Integer[] groupsNumber = new Integer[grps.length];
        if (groupsString.equals("")) {
            groupsNumber = new Integer[0];
        }
        for (int i = 0; i < grps.length; i++) {
            if (!grps[i].equals("")) {
                groupsNumber[i] = new Integer(grps[i]);
            }
        }
        String login = request.getParameter(Registration.loginParameter);
        String password = request.getParameter(Registration.passwordParameter);
        String fName = request.getParameter(Registration.fNameParameter);
        String lName = request.getParameter(Registration.lNameParameter);
        String email = request.getParameter(Registration.emailParameter);
        String county = request.getParameter(Registration.countyParameter);
        String city = request.getParameter(Registration.cityParameter);
        String street = request.getParameter(Registration.streetParameter);
        String home = request.getParameter(Registration.homeParameter);
        String appartment = request.getParameter(Registration.appartmentParameter);
        String longitude = request.getParameter(Registration.longitudeParameter);
        String latitude = request.getParameter(Registration.latitudeParameter);
        boolean successValidate = true;
        SimpleJSONObject json = new SimpleJSONObject();

        if (validate(login, Registration.loginPattern)) {
            json.addProperty(Registration.loginParameter, Registration.ok);
        } else {
            json.addProperty(Registration.loginParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(password, Registration.passwordPattern)) {
            json.addProperty(Registration.passwordParameter, Registration.ok);
        } else {
            json.addProperty(Registration.passwordParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(fName, Registration.fNamePattern)) {
            json.addProperty(Registration.fNameParameter, Registration.ok);
        } else {
            json.addProperty(Registration.fNameParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(lName, Registration.lNamePattern)) {
            json.addProperty(Registration.lNameParameter, Registration.ok);
        } else {
            json.addProperty(Registration.lNameParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(email, Registration.emailPattern)) {
            json.addProperty(Registration.emailParameter, Registration.ok);
        } else {
            json.addProperty(Registration.emailParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(county, Registration.countryPattern)) {
            json.addProperty(Registration.countyParameter, Registration.ok);
        } else {
            json.addProperty(Registration.countyParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(city, Registration.cityPattern)) {
            json.addProperty(Registration.cityParameter, Registration.ok);
        } else {
            json.addProperty(Registration.cityParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(street, Registration.streetPattern)) {
            json.addProperty(Registration.streetParameter, Registration.ok);
        } else {
            json.addProperty(Registration.streetParameter, Registration.wrong);
            successValidate = false;
        }

        if (validate(home, Registration.homePattern)) {
            json.addProperty(Registration.homeParameter, Registration.ok);
        } else {
            json.addProperty(Registration.homeParameter, Registration.wrong);
            successValidate = false;
        }
        if (!successValidate) {
            sendJSON(json, response);
            return;
        }
        boolean existsLogin = false;
        boolean existsEmail = false;

        try {
            InitialContext context = new InitialContext();
            UsersLocalHome homeUser = (UsersLocalHome) context.lookup("java:comp/env/Users");
            existsLogin = homeUser.isLoginExists(login);
            existsEmail = homeUser.isEmailExists(email);
        } catch (NamingException ex) {
            ex.printStackTrace();
        }        
        try {
            InitialContext context = new InitialContext();
            UsersLocalHome homeUser = (UsersLocalHome) context.lookup("java:comp/env/Users");
            UsersLocal local = homeUser.findByPrimaryKey(new Integer(request.getParameter(userIdParameter)));
            AddressLocalHome addressHome = (AddressLocalHome) context.lookup("java:comp/env/Address");            
            User user = local.getUser();
            if (existsLogin || existsEmail) {
                if (existsLogin && !user.getLogin().equals(login)) {
                    json.addProperty(Registration.loginParameter, Registration.exists);
                    sendJSON(json, response);
                    return;
                }
                if (existsEmail && !user.getEmail().equals(email)) {
                    json.addProperty(Registration.emailParameter, Registration.exists);
                    sendJSON(json, response);
                    return;
                }
            }
            ArrayList allRoles = UserRole.getAllRoles();
            allRoles.remove(UserRole.USER);
            ArrayList userRoles = new ArrayList(user.getRoles());
            for (int i = 0; i < rolesNumber.length; i++) {
                UserRole ur = UserRole.instance(rolesNumber[i]);
                if (!userRoles.contains(ur)) {
                    userRoles.add(ur);
                    allRoles.remove(ur);
                }
            }
            for (int i = 0; i < allRoles.size(); i++) {
                userRoles.remove(allRoles.get(i));
            }
            user.setRoles(userRoles);
            user.setLastName(lName);
            user.setLogin(login);
            user.setFirstName(fName);
            user.setPassword(password);
            user.setEmail(email);
            Address address = new Address();
            address.setCountry(county);
            address.setCity(city);
            address.setStreet(street);
            address.setBuilding(home);
            address.setFlat(appartment);
            address.setLongitude(Double.valueOf(longitude));
            address.setLatitude(Double.valueOf(latitude));
            if (!user.getAddress().toString().equals(address.toString())) {
                AddressLocal addressLocal = addressHome.create(address);
                addressLocal.setAddress(address);
                user.setAddress(addressLocal.getAddress());
            }
            local.setUser(user);
            GroupsLocalHome homeGroup = (GroupsLocalHome) context.lookup("java:comp/env/Groups");
            
            ArrayList allGroups = GroupContent.getAllGroups();
            for (int i = 0; i < groupsNumber.length; i++) {                
                GroupsLocal groupsLocal = homeGroup.findByPrimaryKey(groupsNumber[i]);
                Group group = groupsLocal.getGroup();
                ArrayList users = new ArrayList(group.getUsers());
                if (!users.contains(user)) {
                    users.add(user);
                }
                group.setUsers(users);
                groupsLocal.setGroup(group);
            }            
            
            for (int i = 0; i < allGroups.size(); i++) {
                Group g = (Group) allGroups.get(i);
                GroupsLocal groupsLocal = homeGroup.findByPrimaryKey(g.getIdGroup());
                ArrayList users = new ArrayList(g.getUsers());
                boolean flag = true;
                for (int j = 0; j < groupsNumber.length; j++) {
                    if (groupsNumber[j].intValue() == g.getIdGroup().intValue()) {
                        flag = false;
                    }
                }
                if (flag) {
                    users.remove(user);
                    g.setUsers(users);
                    groupsLocal.setGroup(g);
                }
            }
        } catch (NamingException ex) {
            ex.printStackTrace();
        } catch (FinderException ex) {
            ex.printStackTrace();
        } catch (CreateException ex) {
            ex.printStackTrace();
        }
    
        sendJSON(json, response);
    }
    

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
    
    private static boolean validate(String value, String pattern) {
        if (value == null) {
            return false;
        }
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(value);
        return m.matches();
    }

    private static void sendJSON(SimpleJSONObject json, HttpServletResponse response) {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.println(json);
            out.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            out.close();
        }
    }
}
